package signGrammar.view;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

import signGrammar.IShape;
import signGrammar.view.CViewBox.BoxType;
import signGrammar.view.CViewPackageChooser.IPackageChooserListener;
import signGrammar.view.CViewStateButton.IStateButtonListener;

public class CViewMainFrame extends JFrame {
	private static final long serialVersionUID = 1L;
	
	public interface IMainFrameListener{
		public void aboutClicked();
		public void clearClicked();
		public void drawClicked();
		public void packageChoosed(String packageName);
	}

	public CViewMainFrame() {
		initComponents();
		initListeners();
	}

	public CViewMainFrame startUI() {
		setLocationRelativeTo(null);
		setVisible(true);
		return this;
	}

	private CViewStateButton drawClearButton;
	private JButton aboutButton;

	private CViewBox contentPane;
	private CViewBox controlsPane;
	private CViewBox productionsPane;
	private CViewShapePane drawingPane;
	private JPanel derivationPane;
	private JPanel optionsPane;
	
	private CViewPackageChooser packageChooser;

	private CViewGridBox primitivesPane;
	
	private void initComponents() {
		drawClearButton = new CViewStateButton(new String[]{"Draw","Clear"});
		aboutButton = new JButton("About");
		
		controlsPane = new CViewBox(BoxType.HORIZONTAL, drawClearButton, aboutButton );
		controlsPane.setBorder(BorderFactory.createTitledBorder("Controls"));

		derivationPane = new JPanel(new BorderLayout());
		derivationPane.setBorder(BorderFactory.createTitledBorder("Derivation"));
		derivationPane.setPreferredSize(new Dimension(300, 130));

		optionsPane = new JPanel();
		optionsPane.setLayout( new BoxLayout( optionsPane, BoxLayout.PAGE_AXIS ) );
		optionsPane.setMinimumSize( new Dimension(300, 130) );
		optionsPane.setPreferredSize( new Dimension(300, 130) );
		optionsPane.setBorder( BorderFactory.createTitledBorder("Options") );
		
		drawingPane = new CViewShapePane();
		drawingPane.setPreferredSize(new Dimension(700, 130));
		
		primitivesPane = new CViewGridBox(BoxType.VERTICAL).setBreakPoint(3);
		primitivesPane.setPreferredSize(new Dimension(200, 100));
		primitivesPane.setBoxBorder( BorderFactory.createTitledBorder("Primitives") );
		
		productionsPane = new CViewBox(BoxType.VERTICAL );
		productionsPane.setPreferredSize(new Dimension(100, 100));
		productionsPane.setBoxBorder( BorderFactory.createTitledBorder("Productions") );
		
		JPanel bottomPane = new JPanel(new BorderLayout());
		bottomPane.setBorder(BorderFactory.createTitledBorder(""));
		bottomPane.add(drawingPane, "Center");

		CViewBox mainPane = new CViewBox( BoxType.VERTICAL,
			derivationPane,
			optionsPane,
			controlsPane
		);

		packageChooser = new CViewPackageChooser();
		
		JPanel productionPrimitivesPane = new JPanel(new BorderLayout());
		productionPrimitivesPane.add( packageChooser, "North");
		productionPrimitivesPane.add(new CViewBox(BoxType.HORIZONTAL,productionsPane,primitivesPane),"Center");
		
		CViewBox topPane = new CViewBox( BoxType.HORIZONTAL,
			mainPane,
			productionPrimitivesPane
		);
		
		contentPane = new CViewBox(BoxType.VERTICAL,
			topPane,
			bottomPane
		);
		getContentPane().add(contentPane, "Center");
		
		setTitle("Grammar");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		pack();
	}

	private void initListeners() {
		drawClearButton.addListener( new IStateButtonListener(){
			@Override public void stateChanged(String oldState, String newState) {
				if( "Draw".equals(oldState) )
					publishDrawClicked();
				else
					publishClearClicked();
			}} );
		aboutButton.addActionListener(new ActionListener() {
			@Override public void actionPerformed(ActionEvent e) {
				publishAboutClicked();
			}});
		packageChooser.addPackageListener(new IPackageChooserListener(){
			@Override public void packageChoosed(String packageName) {
				publishPackageNameCHoosed(packageName);
			}});
	}

	private void publishPackageNameCHoosed(String packageName){
		for( IMainFrameListener l : mainFrameListeners )
			l.packageChoosed(packageName);
	}
	
	private void publishDrawClicked(){
		for( IMainFrameListener l : mainFrameListeners )
			l.drawClicked();
	}
	
	private void publishClearClicked(){
		for( IMainFrameListener l : mainFrameListeners )
			l.clearClicked();
	}
	
	private void publishAboutClicked(){
		for( IMainFrameListener l : mainFrameListeners )
			l.aboutClicked();
	}
	
	private CViewMainFrame setAsContentOf(JPanel target, JPanel content, JComponent[] components){
		for (JComponent comp : components)
			content.add(comp);
		target.removeAll();
		target.add(content, "Center");
		target.setVisible(false);
		target.setVisible(true);
		return this;
	}
	
	public CViewMainFrame setPrimitives(Map<String, IShape> primitivies){
		primitivesPane.removeAll();
		for (String name: primitivies.keySet())
			primitivesPane.add( new CViewShapePane( primitivies.get(name), name ) );
		return this;
	}
	public CViewMainFrame setProductions( JComponent[] components ){
		productionsPane.removeAll();
		for ( JComponent component : components )
			productionsPane.add( component );
		return this;
	}
	public CViewMainFrame setPackagesChoises(String[] packages){
		packageChooser.setChoises(packages);
		return this;
	}
	
	public CViewMainFrame drawShape( IShape shape ){
		drawingPane.setShape(shape);
		return this;
	}
	public CViewMainFrame setDeductionContent(JComponent[] components){
		return setAsContentOf(derivationPane, new JPanel( new FlowLayout( FlowLayout.LEFT ) ),components);
	}
	public CViewMainFrame clearDeductionContent(){
		setAsContentOf(derivationPane, new JPanel( new FlowLayout( FlowLayout.LEFT ) ), new JComponent[]{} );
		return this;
	}
	public CViewMainFrame setOptionsContent(JComponent[] components){
		return setAsContentOf(optionsPane, new JPanel( new FlowLayout( FlowLayout.LEFT ) ),components);
	}
	public CViewMainFrame clearOptionContent(){
		return setAsContentOf(optionsPane, new JPanel( new FlowLayout( FlowLayout.LEFT ) ), new JComponent[]{} );
	}
	public CViewMainFrame clearDrawingPane() {
		drawingPane.setShape(null);
		return this;
	}
	public CViewMainFrame setDrawClearButtonState(String state){
		drawClearButton.setState(state);
		return this;
	}
	
	protected ArrayList<IMainFrameListener> mainFrameListeners = new ArrayList<IMainFrameListener>();
	public CViewMainFrame addListener( IMainFrameListener list ){
		mainFrameListeners.add(list);
		return this;
	}
	public boolean removeListener(IMainFrameListener list){
		return mainFrameListeners.remove(list);
	}
}